/***********************************************************
 * Product Name: ExcelQuicker
 * Copyright (c)2005, Eunge
 * Author: Eunge
 * Web Site: www.eudev.net
 * Mail/MSN: eudev.net@yeah.net
 * ********************************************************/
using System;
using System.Globalization;
using System.Security.Permissions;
using System.Data;
using System.Runtime.Serialization;

namespace ExcelQuicker.Framework
{
	/// <summary>
	/// The message class of ExcelQuicker, implementing multi-language messages and handling exception or system message
	/// </summary>
	/// <example>
	/// <br>EQException exp = new EQException("EQ1002");	//It will read exception descrition from message xml file by code "EQ1002"</br>
	/// <br>throw exp;	//Throw a exception, just like class Exception.</br>
	/// <br></br>
	/// <br>throw new EQException("EQ1003", strYourDesc)</br>
	/// <br>//EQException class will use string strYourDesc instead of {x} of the corresponding description in xml file.</br>
	/// </example>
	[Serializable]
	public class EQException: Exception 
	{
		private static string mLanguage = "";
		private static string mXMLFileName = "";
		private string mCode = "";
		private string mDescription = "";

		/// <summary>
		/// Call base GetObjectData() function
		/// </summary>
		/// <param name="info"></param>
		/// <param name="context"></param>
		[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			base.GetObjectData (info, context);
		}


		/// <summary>
		/// Get message code
		/// </summary>
		public string Code
		{
			get
			{
				return this.mCode;
			}
		}

		/// <summary>
		/// Get message description
		/// </summary>
		public string Description
		{
			get
			{
				return this.mDescription;
			}
		}

		/// <summary>
		/// Get full message, integrating with message code and its description
		/// </summary>
		public override string Message
		{
			get
			{
				return "(" + this.mCode + ")" + this.mDescription;
			}
		}

		/// <summary>
		/// Static constructor
		/// </summary>
		static EQException()
		{
			if(!ExistLanguage(EQConfiguration.Language, EQConfiguration.XmlFileName))
			{
				throw new Exception("(EQException)The message language [" + EQConfiguration.Language + "] doesn't exist in message file.");
			}

			mXMLFileName = EQConfiguration.XmlFileName;
			mLanguage = EQConfiguration.Language;
		}

		/// <summary>
		/// Initialize object
		/// </summary>
		public EQException(){}

		/// <summary>
		/// Initialize object by message code
		/// </summary>
		/// <param name="code">Message code</param>
		public EQException(string code)
		{
			this.mCode = code;
			this.mDescription = EQException.GetDescription(code);
		}

		/// <summary>
		/// Initialize object by message code and seld-defined message
		/// </summary>
		/// <param name="code">Message code</param>
		/// <param name="msg">Self-defined message, instead of {X} in the message description</param>
		public EQException(string code, params string[] msg)
		{
			this.mCode = code;
			string strDesc = EQException.GetDescription(code);
			this.mDescription = string.Format(strDesc, msg);
		}

		/// <summary>
		/// Initialize object from a inner exception
		/// </summary>
		/// <param name="e">Exception</param>
		public EQException(System.Exception e)
		{					
			this.mCode = "Excel COM";
			this.mDescription = e.Message.ToString ();
		}

		/// <summary>
		/// Initialize object from message code and inner exception
		/// </summary>
		/// <param name="code">Message code</param>
		/// <param name="e"></param>
		public EQException(string code, System.Exception e)
		{
			this.mCode = code;
			this.mDescription = e.Message.ToString ();
		}

		/// <summary>
		/// Initialize object from message code, seld-defined message and inner exception
		/// </summary>
		/// <param name="code">Message code</param>
		/// <param name="msg">Self-defined message, instead of {X} in the message description</param>
		/// <param name="e"></param>
		public EQException(string code, System.Exception e, params string[] msg)
		{
			this.mCode = code;
			string strDesc = EQException.GetDescription(code);
			this.mDescription = string.Format(strDesc, msg);
			this.mDescription = e.Message.ToString ();
		}
		
		/// <summary>
		/// Initialize object by derived constructor
		/// </summary>
		/// <param name="info"></param>
		/// <param name="context"></param>
		protected EQException(SerializationInfo info, StreamingContext context) : base(info, context){}

		/// <summary>
		/// Return description from message code
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		public static string GetDescription(string code)
		{
			DataSet dst = new DataSet();
			dst.Locale = CultureInfo.CurrentCulture;
			dst.ReadXml(EQException.mXMLFileName);
			DataView dvw = dst.Tables[0].DefaultView;
			foreach(DataRowView dvrow in dvw)
				if(code == dvrow["MessageCode"].ToString())
					return dvrow[EQException.mLanguage].ToString();
			return "";
		}


		/// <summary>
		/// Check whether the setting of message language was exist in the xml file
		/// </summary>
		/// <param name="language">Language tag</param>
		/// <param name="xmlFileName">Xml full physical file name</param>
		/// <returns></returns>
		public static bool ExistLanguage(string language, string xmlFileName)
		{
			DataSet dst = new DataSet();
			dst.Locale = CultureInfo.CurrentCulture;
			dst.ReadXml(xmlFileName);
			DataTable dtbl = dst.Tables[0];
			for(int i=0; i<dtbl.Columns.Count; i++)
				if(language == dtbl.Columns[i].ColumnName)
					return true;
			return false;
		}
	}
}
